package com.ruoyi.huanjing.controller;

import java.io.*;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.*;
import org.knowm.xchart.*;
import org.knowm.xchart.style.Styler;

public class ElectromagneticDataParser {

    // 数据结构定义
    static class DataBlock {
        String name;
        int length;
        double[] data;

        public DataBlock(String name, int length, double[] data) {
            this.name = name;
            this.length = length;
            this.data = data;
        }
    }

    static class DistancePulseData {
        double[] rangeGates;
        double[] pulses;
        double[][] realPart;
        double[][] imagPart;

        public DistancePulseData(double[] rangeGates, double[] pulses, double[][] realPart, double[][] imagPart) {
            this.rangeGates = rangeGates;
            this.pulses = pulses;
            this.realPart = realPart;
            this.imagPart = imagPart;
        }
    }

    static class TimeDopplerSpectrum {
        double[] dopplerFrequencies;
        double[] times;
        double[][] spectrumDensity;

        public TimeDopplerSpectrum(double[] dopplerFrequencies, double[] times, double[][] spectrumDensity) {
            this.dopplerFrequencies = dopplerFrequencies;
            this.times = times;
            this.spectrumDensity = spectrumDensity;
        }
    }

    // 字节序枚举
    enum ByteOrderType {
        LITTLE_ENDIAN,
        BIG_ENDIAN
    }

    // 主程序
    public static void main(String[] args) {
        String filePath = "D:\\项目\\环境预览\\【内部】202405180300_YS_SS2_149_SeaPara.bin";
        File file = new File(filePath);

        if (!file.exists()) {
            System.out.println("文件不存在: " + filePath);
            return;
        }

        try {
            // 尝试检测字节序
            ByteOrderType byteOrder = detectByteOrder(file);
            System.out.println("检测到的字节序: " + byteOrder);

            // 读取并解析文件
            parseElectromagneticFile(file, byteOrder);
        } catch (IOException e) {
            System.out.println("读取文件时出错: " + e.getMessage());
            e.printStackTrace();
        }
    }

    // 检测文件字节序
    // 检测文件字节序
    private static ByteOrderType detectByteOrder(File file) throws IOException {
        try (DataInputStream dis = new DataInputStream(new BufferedInputStream(new FileInputStream(file)))) {
            // 设置标记，允许读取足够的字节来检测字节序
            dis.mark(1024); // 标记当前位置，并允许最多读取1024字节后仍能reset

            // 尝试以小端序读取长度
            int littleEndianLength = dis.readInt();
            dis.reset(); // 回到标记位置

            // 尝试以大端序读取长度
            byte[] bytes = new byte[4];
            dis.readFully(bytes);
            int bigEndianLength = ByteBuffer.wrap(bytes).order(ByteOrder.BIG_ENDIAN).getInt();
            dis.reset(); // 回到标记位置

            // 判断哪个字节序更合理（长度为正整数且不超过文件大小）
            long fileSize = file.length();
            boolean littleEndianValid = littleEndianLength > 0 && littleEndianLength * 8 <= fileSize;
            boolean bigEndianValid = bigEndianLength > 0 && bigEndianLength * 8 <= fileSize;

            if (littleEndianValid && !bigEndianValid) {
                return ByteOrderType.LITTLE_ENDIAN;
            } else if (!littleEndianValid && bigEndianValid) {
                return ByteOrderType.BIG_ENDIAN;
            } else {
                // 如果无法判断，默认使用小端序（可根据实际情况调整）
                System.out.println("无法确定字节序，默认使用小端序");
                return ByteOrderType.LITTLE_ENDIAN;
            }
        }
    }

    private static void parseElectromagneticFile(File file, ByteOrderType byteOrder) throws IOException {
        System.out.println("开始解析电磁特性数据文件: " + file.getName());

        try (DataInputStream dis = new DataInputStream(new BufferedInputStream(new FileInputStream(file)))) {
            // 读取文件总长度
            long fileLength = file.length();
            System.out.println("文件总长度: " + fileLength + " 字节");

            // 读取各数据块
            Map<String, DataBlock> dataBlocks = new LinkedHashMap<>();

            // 平均散射系数
            DataBlock avgScattering = readDataBlock(dis, "平均散射系数", byteOrder);
            dataBlocks.put("平均散射系数", avgScattering);

            // 时变散射系数
            DataBlock timeVaryingScattering = readDataBlock(dis, "时变散射系数", byteOrder);
            dataBlocks.put("时变散射系数", timeVaryingScattering);

            // 幅度概率密度
            DataBlock amplitudePDF = readDataBlock(dis, "幅度概率密度", byteOrder);
            dataBlocks.put("幅度概率密度", amplitudePDF);

            // 时间相关特性
            DataBlock timeCorrelation = readDataBlock(dis, "时间相关特性", byteOrder);
            dataBlocks.put("时间相关特性", timeCorrelation);

            // 距离相关特性
            DataBlock rangeCorrelation = readDataBlock(dis, "距离相关特性", byteOrder);
            dataBlocks.put("距离相关特性", rangeCorrelation);

            // 多普勒谱
            DataBlock dopplerSpectrum = readDataBlock(dis, "多普勒谱", byteOrder);
            dataBlocks.put("多普勒谱", dopplerSpectrum);

            // 一维图像
            DataBlock image1D = readDataBlock(dis, "一维图像", byteOrder);
            dataBlocks.put("一维图像", image1D);

            // 距离-脉冲数据
            DistancePulseData rangePulseData = readRangePulseData(dis, byteOrder);

            // 时变多普勒谱
            TimeDopplerSpectrum timeDopplerData = readTimeDopplerSpectrum(dis, byteOrder);

            // 输出数据摘要
            printDataSummary(dataBlocks, rangePulseData, timeDopplerData);

            // 可视化部分数据
            if (validateDataBlocks(dataBlocks)) {
                visualizeData(dataBlocks, rangePulseData, timeDopplerData);
            } else {
                System.out.println("数据验证失败，跳过可视化");
            }

            System.out.println("文件解析完成!");
        }
    }

    // 验证数据块是否有效
    private static boolean validateDataBlocks(Map<String, DataBlock> dataBlocks) {
        for (DataBlock block : dataBlocks.values()) {
            if (block.length <= 0 || block.data == null || block.data.length == 0) {
                System.out.println("无效数据块: " + block.name + ", 长度: " + block.length);
                return false;
            }
        }
        return true;
    }

    // 读取通用数据块（int长度 + 2*N个double值）
    private static DataBlock readDataBlock(DataInputStream dis, String blockName, ByteOrderType byteOrder) throws IOException {
        System.out.println("\n读取数据块: " + blockName);

        try {
            // 根据字节序读取长度
            int length = readIntWithByteOrder(dis, byteOrder);

            // 验证长度是否合理
            if (length <= 0) {
                System.out.println("警告: " + blockName + " 的长度为负数或零: " + length);
                return new DataBlock(blockName, length, new double[0]);
            }

            System.out.println(blockName + " 长度: " + length);

            // 读取2*N个double值
            double[] data = new double[length * 2];
            for (int i = 0; i < length * 2; i++) {
                data[i] = readDoubleWithByteOrder(dis, byteOrder);
            }

            System.out.println(blockName + " 数据读取完成，共 " + data.length + " 个double值");
            return new DataBlock(blockName, length, data);
        } catch (EOFException e) {
            System.out.println("错误: 读取" + blockName + "时到达文件末尾");
            return new DataBlock(blockName, 0, new double[0]);
        } catch (IOException e) {
            System.out.println("错误: 读取" + blockName + "时发生IO异常: " + e.getMessage());
            throw e;
        }
    }

    // 读取距离-脉冲数据
    private static DistancePulseData readRangePulseData(DataInputStream dis, ByteOrderType byteOrder) throws IOException {
        System.out.println("\n读取距离-脉冲数据");

        try {
            // 读取距离门数据
            int m = readIntWithByteOrder(dis, byteOrder);
            System.out.println("距离门数据长度: " + m);
            double[] rangeGates = new double[m];
            for (int i = 0; i < m; i++) {
                rangeGates[i] = readDoubleWithByteOrder(dis, byteOrder);
            }

            // 读取脉冲数数据
            int n = readIntWithByteOrder(dis, byteOrder);
            System.out.println("脉冲数数据长度: " + n);
            double[] pulses = new double[n];
            for (int i = 0; i < n; i++) {
                pulses[i] = readDoubleWithByteOrder(dis, byteOrder);
            }

            // 读取实部数据（M*N个double）
            double[][] realPart = new double[n][m];
            for (int j = 0; j < n; j++) {
                for (int i = 0; i < m; i++) {
                    realPart[j][i] = readDoubleWithByteOrder(dis, byteOrder);
                }
            }

            // 读取虚部数据（M*N个double）
            double[][] imagPart = new double[n][m];
            for (int j = 0; j < n; j++) {
                for (int i = 0; i < m; i++) {
                    imagPart[j][i] = readDoubleWithByteOrder(dis, byteOrder);
                }
            }

            System.out.println("距离-脉冲数据读取完成");
            return new DistancePulseData(rangeGates, pulses, realPart, imagPart);
        } catch (EOFException e) {
            System.out.println("错误: 读取距离-脉冲数据时到达文件末尾");
            return new DistancePulseData(new double[0], new double[0], new double[0][0], new double[0][0]);
        } catch (IOException e) {
            System.out.println("错误: 读取距离-脉冲数据时发生IO异常: " + e.getMessage());
            throw e;
        }
    }

    // 读取时变多普勒谱
    private static TimeDopplerSpectrum readTimeDopplerSpectrum(DataInputStream dis, ByteOrderType byteOrder) throws IOException {
        System.out.println("\n读取时变多普勒谱");

        try {
            // 读取多普勒频率数据
            int p = readIntWithByteOrder(dis, byteOrder);
            System.out.println("多普勒频率数据长度: " + p);
            double[] dopplerFrequencies = new double[p];
            for (int i = 0; i < p; i++) {
                dopplerFrequencies[i] = readDoubleWithByteOrder(dis, byteOrder);
            }

            // 读取时间数据
            int q = readIntWithByteOrder(dis, byteOrder);
            System.out.println("时间数据长度: " + q);
            double[] times = new double[q];
            for (int i = 0; i < q; i++) {
                times[i] = readDoubleWithByteOrder(dis, byteOrder);
            }

            // 读取多普勒谱密度数据（P*Q个double）
            double[][] spectrumDensity = new double[q][p];
            for (int j = 0; j < q; j++) {
                for (int i = 0; i < p; i++) {
                    spectrumDensity[j][i] = readDoubleWithByteOrder(dis, byteOrder);
                }
            }

            System.out.println("时变多普勒谱数据读取完成");
            return new TimeDopplerSpectrum(dopplerFrequencies, times, spectrumDensity);
        } catch (EOFException e) {
            System.out.println("错误: 读取时变多普勒谱时到达文件末尾");
            return new TimeDopplerSpectrum(new double[0], new double[0], new double[0][0]);
        } catch (IOException e) {
            System.out.println("错误: 读取时变多普勒谱时发生IO异常: " + e.getMessage());
            throw e;
        }
    }

    // 根据字节序读取int
    private static int readIntWithByteOrder(DataInputStream dis, ByteOrderType byteOrder) throws IOException {
        if (byteOrder == ByteOrderType.LITTLE_ENDIAN) {
            return dis.readInt(); // DataInputStream默认使用大端序
        } else {
            // 手动实现大端序读取
            byte[] bytes = new byte[4];
            dis.readFully(bytes);
            return ByteBuffer.wrap(bytes).order(ByteOrder.BIG_ENDIAN).getInt();
        }
    }

    // 根据字节序读取double
    private static double readDoubleWithByteOrder(DataInputStream dis, ByteOrderType byteOrder) throws IOException {
        if (byteOrder == ByteOrderType.LITTLE_ENDIAN) {
            return dis.readDouble(); // DataInputStream默认使用大端序
        } else {
            // 手动实现大端序读取
            byte[] bytes = new byte[8];
            dis.readFully(bytes);
            return ByteBuffer.wrap(bytes).order(ByteOrder.BIG_ENDIAN).getDouble();
        }
    }

    // 打印数据摘要
    private static void printDataSummary(Map<String, DataBlock> dataBlocks,
                                         DistancePulseData rangePulseData,
                                         TimeDopplerSpectrum timeDopplerData) {
        System.out.println("\n=== 数据摘要 ===");

        // 打印各数据块统计信息
        for (Map.Entry<String, DataBlock> entry : dataBlocks.entrySet()) {
            DataBlock block = entry.getValue();
            if (block.data.length == 0) {
                continue;
            }

            double min = Double.MAX_VALUE;
            double max = Double.MIN_VALUE;
            double sum = 0;

            for (double value : block.data) {
                min = Math.min(min, value);
                max = Math.max(max, value);
                sum += value;
            }

            double avg = sum / block.data.length;

            System.out.printf("%s: 长度=%d, 数据点数=%d, 最小值=%.6f, 最大值=%.6f, 平均值=%.6f\n",
                    block.name, block.length, block.data.length, min, max, avg);
        }

        // 距离-脉冲数据统计
        if (rangePulseData.rangeGates.length > 0 && rangePulseData.pulses.length > 0) {
            System.out.printf("距离-脉冲数据: M=%d, N=%d, 数据大小=%.2f KB\n",
                    rangePulseData.rangeGates.length,
                    rangePulseData.pulses.length,
                    (rangePulseData.rangeGates.length * rangePulseData.pulses.length * 2 * 8) / 1024.0);
        }

        // 时变多普勒谱统计
        if (timeDopplerData.dopplerFrequencies.length > 0 && timeDopplerData.times.length > 0) {
            System.out.printf("时变多普勒谱: P=%d, Q=%d, 数据大小=%.2f KB\n",
                    timeDopplerData.dopplerFrequencies.length,
                    timeDopplerData.times.length,
                    (timeDopplerData.dopplerFrequencies.length * timeDopplerData.times.length * 8) / 1024.0);
        }
    }

    // 可视化部分数据
    private static void visualizeData(Map<String, DataBlock> dataBlocks,
                                      DistancePulseData rangePulseData,
                                      TimeDopplerSpectrum timeDopplerData) {
        try {
            // 可视化一维图像数据
            if (dataBlocks.containsKey("一维图像")) {
                DataBlock image1D = dataBlocks.get("一维图像");
                if (image1D.data.length > 0) {
                    visualize1DImage(image1D);
                }
            }

            // 可视化多普勒谱
            if (dataBlocks.containsKey("多普勒谱")) {
                DataBlock doppler = dataBlocks.get("多普勒谱");
                if (doppler.data.length > 0) {
                    visualizeDopplerSpectrum(doppler);
                }
            }

            // 可视化距离-脉冲数据（只显示前10个脉冲）
            if (rangePulseData != null && rangePulseData.rangeGates.length > 0 && rangePulseData.pulses.length > 0) {
                visualizeRangePulseData(rangePulseData);
            }

            // 可视化时变多普勒谱（热力图）
            if (timeDopplerData != null && timeDopplerData.dopplerFrequencies.length > 0 && timeDopplerData.times.length > 0) {
                visualizeTimeDopplerSpectrum(timeDopplerData);
            }

        } catch (Exception e) {
            System.out.println("可视化过程中出错: " + e.getMessage());
            e.printStackTrace();
        }
    }

    // 可视化一维图像数据
    private static void visualize1DImage(DataBlock image1D) {
        // 假设前半部分是实部，后半部分是虚部
        int n = image1D.length;
        if (n * 2 > image1D.data.length) {
            n = image1D.data.length / 2; // 防止数组越界
        }

        double[] real = Arrays.copyOfRange(image1D.data, 0, n);
        double[] imag = Arrays.copyOfRange(image1D.data, n, Math.min(2 * n, image1D.data.length));

        // 计算幅度
        double[] amplitude = new double[n];
        for (int i = 0; i < n; i++) {
            amplitude[i] = Math.sqrt(real[i] * real[i] + imag[i] * imag[i]);
        }

        // 创建图表
        CategoryChart chart = new CategoryChartBuilder()
                .width(800)
                .height(600)
                .title("一维图像")
                .xAxisTitle("采样点")
                .yAxisTitle("幅度")
                .build();

        // 设置样式
        chart.getStyler().setLegendPosition(Styler.LegendPosition.InsideNW);

        // 添加数据
        List<Integer> xData = new ArrayList<>();
        List<Double> yData = new ArrayList<>();
        for (int i = 0; i < n; i++) {
            xData.add(i);
            yData.add(amplitude[i]);
        }

        chart.addSeries("幅度", xData, yData);

        // 显示图表
        new SwingWrapper<>(chart).displayChart();
    }

    // 可视化多普勒谱
    private static void visualizeDopplerSpectrum(DataBlock doppler) {
        // 假设前半部分是频率，后半部分是功率
        int n = doppler.length;
        if (n * 2 > doppler.data.length) {
            n = doppler.data.length / 2; // 防止数组越界
        }

        double[] frequency = Arrays.copyOfRange(doppler.data, 0, n);
        double[] power = Arrays.copyOfRange(doppler.data, n, Math.min(2 * n, doppler.data.length));

        // 创建图表
        XYChart chart = new XYChartBuilder()
                .width(800)
                .height(600)
                .title("多普勒谱")
                .xAxisTitle("频率")
                .yAxisTitle("功率")
                .build();

        // 设置样式
        chart.getStyler().setLegendPosition(Styler.LegendPosition.InsideNW);

        // 添加数据
        chart.addSeries("多普勒谱", frequency, power);

        // 显示图表
        new SwingWrapper<>(chart).displayChart();
    }

    // 可视化距离-脉冲数据
    private static void visualizeRangePulseData(DistancePulseData data) {
        int m = data.rangeGates.length;  // 距离门数量
        int n = data.pulses.length;      // 脉冲数量

        if (m == 0 || n == 0) {
            return;
        }

        // 只显示前10个脉冲以避免图表过于拥挤
        int displayPulses = Math.min(10, n);

        // 创建图表
        XYChart chart = new XYChartBuilder()
                .width(800)
                .height(600)
                .title("距离-脉冲数据")
                .xAxisTitle("距离门")
                .yAxisTitle("幅度")
                .build();

        // 设置样式
        chart.getStyler().setLegendPosition(Styler.LegendPosition.InsideNW);

        // 计算每个脉冲的幅度（实部和虚部的模）
        for (int j = 0; j < displayPulses; j++) {
            double[] amplitude = new double[m];
            for (int i = 0; i < m; i++) {
                amplitude[i] = Math.sqrt(data.realPart[j][i] * data.realPart[j][i] +
                        data.imagPart[j][i] * data.imagPart[j][i]);
            }

            chart.addSeries("脉冲 #" + (j+1), data.rangeGates, amplitude);
        }

        // 显示图表
        new SwingWrapper<>(chart).displayChart();
    }

    // 可视化时变多普勒谱（热力图）
    private static void visualizeTimeDopplerSpectrum(TimeDopplerSpectrum data) {
        int p = data.dopplerFrequencies.length;  // 多普勒频率点数
        int q = data.times.length;               // 时间点数

        if (p == 0 || q == 0) {
            return;
        }

        // 创建热力图数据
        double[][] heatmapData = new double[q][p];

        // 转置数据以适应XChart的热力图要求
        for (int j = 0; j < q; j++) {
            for (int i = 0; i < p; i++) {
                heatmapData[j][i] = data.spectrumDensity[j][i];
            }
        }

        // 创建热力图
        CategoryChart chart = new CategoryChartBuilder()
                .width(800)
                .height(600)
                .title("时变多普勒谱")
                .xAxisTitle("多普勒频率")
                .yAxisTitle("时间")
                .build();

        // 设置样式
        chart.getStyler().setLegendPosition(Styler.LegendPosition.InsideNE);
        chart.getStyler().setXAxisLabelRotation(45);

        // 添加数据
        List<Integer> xData = new ArrayList<>();
        for (int i = 0; i < p; i++) {
            xData.add(i);
        }

        for (int j = 0; j < q; j++) {
            // 将double[]转换为List<Double>
            List<Double> yData = new ArrayList<>();
            for (double value : heatmapData[j]) {
                yData.add(value);
            }
            chart.addSeries("时间点 " + j, xData, yData);
        }

        // 显示图表
        new SwingWrapper<>(chart).displayChart();
    }
}